package cc.rengu.igas.bsps.core.service.trans;

import cc.rengu.igas.bsps.common.dao.BspsMchntBaseInfoMapper;
import cc.rengu.igas.bsps.common.dao.BspsTxnLimitCfgMapper;
import cc.rengu.igas.bsps.common.dao.impl.BspsMchntBaseInfoMapperImpl;
import cc.rengu.igas.bsps.common.dao.impl.BspsTxnLimitCfgMapperImpl;
import cc.rengu.igas.bsps.common.entity.MchntBaseInfo;
import cc.rengu.igas.bsps.common.entity.TxnLimitCfg;
import cc.rengu.igas.bsps.common.enums.LimitAcctTypeEnum;
import cc.rengu.igas.bsps.common.enums.MchntLimitEnum;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.service.base.ManageService;
import cc.rengu.igas.bsps.facade.bean.MchntLimitInfoBean;
import cc.rengu.igas.bsps.facade.request.MchntQuotaInfoQueryRequest;
import cc.rengu.igas.bsps.facade.response.MchntQuotaInfoQueryResponse;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.TxnLimitStatisMapper;
import cc.rengu.oltp.service.common.dao.impl.TxnLimitStatisMapperImpl;
import cc.rengu.oltp.service.common.entity.TxnLimitStatis;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.AmountUtil;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zhangxuran
 * @version 1.0
 * @date 2020/04/07
 */
public class MchntQuotaInfoQueryService extends ManageService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        MchntQuotaInfoQueryRequest mchntQuotaInfoQueryRequest = new MchntQuotaInfoQueryRequest();
        ConvertUtil.convertOutput(mchntQuotaInfoQueryRequest);
        return mchntQuotaInfoQueryRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        MchntQuotaInfoQueryRequest mchntQuotaInfoQueryRequest = (MchntQuotaInfoQueryRequest) request;
        /*获取请求报文相关参数：法人行号，用户标识，商户号*/
        String instId = mchntQuotaInfoQueryRequest.getHeader().getInstId();
        String userId = mchntQuotaInfoQueryRequest.getUserId();
        String mchntNo = mchntQuotaInfoQueryRequest.getMchntNo();
        String limitType = mchntQuotaInfoQueryRequest.getLimitType();
        /*参数必填性校验*/
        if (StringUtil.isEmptyOrNull(userId) || StringUtil.isEmptyOrNull(mchntNo) || StringUtil.isEmptyOrNull(instId) || StringUtil.isEmptyOrNull(limitType)) {
            rglog.error("用户标识<{}>，商户号<{}>不能为空!", userId, mchntNo);
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        /*查询商户基本信息*/
        BspsMchntBaseInfoMapper bspsMchntBaseInfoMapper = new BspsMchntBaseInfoMapperImpl();
        MchntBaseInfo mchntBaseInfo = bspsMchntBaseInfoMapper.selectBspsMchntBaseInfoByPrimaryKey(instId, mchntNo);
        if (null == mchntBaseInfo) {
            rglog.error("商户信息查询失败");
            throw new BizException(RespCodeEnum.QUERY_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.QUERY_MCHNT_BASE_INFO_ERROR.getRespDesc());
        }
        /*商户等级赋值*/
        String mchntLevel = mchntBaseInfo.getMchntLevel();
        /*商户组别（经营范围）赋值*/
        String mchntGroup = mchntBaseInfo.getManagementScope();
        /*MCC赋值*/
        String mchntMcc = mchntBaseInfo.getIndustryType();
        /*根据查询类型赋值查询实体:默认商户号*/
        String limitInst;
        List<MchntLimitInfoBean> mchntLimitInfoList = new ArrayList<>();

        switch (limitType) {
            case "01":
                /*商户等级限额*/
                limitInst = mchntLevel;
                break;
            case "02":
                /*商户组别限额*/
                limitInst = mchntGroup;
                break;
            case "03":
                /*MCC限额*/
                limitInst = mchntMcc;
                break;
            case "11":
            case "14":
                /*商户限额或者商户退款限额*/
                limitInst = mchntNo;
                break;
            default:
                rglog.error("限额类型错误");
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        rglog.info("限额查询开始，限额类型：<{}>", limitType);
        queryMchntLimitInfo(instId, mchntNo, limitType, limitInst, mchntLimitInfoList);
        if (CollectionUtils.isEmpty(mchntLimitInfoList) && "11".equals(limitType)) {
            queryMchntLimitInfo(instId, mchntNo, "01", mchntLevel, mchntLimitInfoList);
            if (CollectionUtils.isEmpty(mchntLimitInfoList)) {
                queryMchntLimitInfo(instId, mchntNo, "03", mchntMcc, mchntLimitInfoList);
                if (CollectionUtils.isEmpty(mchntLimitInfoList)) {
                    queryMchntLimitInfo(instId, mchntNo, "02", mchntGroup, mchntLimitInfoList);
                }
            }
        }

        /*组装报文*/
        MchntQuotaInfoQueryResponse mchntQuotaInfoQueryResponse = new MchntQuotaInfoQueryResponse();
        mchntQuotaInfoQueryResponse.setMchntLimitInfoList(mchntLimitInfoList);
        BizResponse<MchntQuotaInfoQueryResponse> bizResponse = new BizResponse<>();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(mchntQuotaInfoQueryResponse);
        return bizResponse;
    }

    /**
     * 查询商户限额信息并转换信息
     * limitType 限额类型
     * limitInst 限额主体
     * mchntLimitInfoList 限额信息列表
     **/
    private void queryMchntLimitInfo(String instId, String mchntNo, String limitType, String limitInst, List<MchntLimitInfoBean> mchntLimitInfoList) {
        try {
            MchntLimitInfoBean mchntLimitInfo = new MchntLimitInfoBean();
            /*限额类型赋值*/
            mchntLimitInfo.setLimitType(limitType);
            /*限额主体赋值*/
            mchntLimitInfo.setLimitInst(limitInst);
            /*限额对象赋值*/
            mchntLimitInfo.setStatisKey(limitInst);
            /*根据限额类型及主体查询限额配置信息*/
            BspsTxnLimitCfgMapper bspsTxnLimitCfgMapper = new BspsTxnLimitCfgMapperImpl();
            /*常规分借贷记及不分区账户三条数据*/
            List<TxnLimitCfg> txnLimitCfgs = bspsTxnLimitCfgMapper.selectBspsLimitInfoByLimitTypeAndLimitInst(instId, limitType, limitInst);
            if (!CollectionUtils.isEmpty(txnLimitCfgs)) {
                //限额配置信息赋值
                for (TxnLimitCfg txnLimitCfg : txnLimitCfgs) {
                    if (LimitAcctTypeEnum.TOTAL_DEBIT.getLimitAcctType().equals(txnLimitCfg.getLimitAcctType())) {
                        /*借记卡限额信息赋值*/
                        if (MchntLimitEnum.MCHNT_REFUND.getLimitType().equals(limitType)) {
                            /*借记账户单笔退款限额赋值*/
                            mchntLimitInfo.setOneDebitAmt(txnLimitCfg.getSingleRefundLimitAmt());
                            /*借记账户日累计退款限额赋值*/
                            mchntLimitInfo.setDebitDayTransAmt(txnLimitCfg.getDayRefundLimitAmt());
                        } else {
                            /*借记账户单笔限额赋值*/
                            mchntLimitInfo.setOneDebitAmt(txnLimitCfg.getSingleLimitMaxAmt());
                            /*借记账户日累计限额赋值*/
                            mchntLimitInfo.setDebitDayTransAmt(txnLimitCfg.getDayLimitAmt());
                            /*借记账户月累计限额赋值*/
                            mchntLimitInfo.setDebitMonthTransAmt(txnLimitCfg.getMonthLimitAmt());
                        }
                    } else if (LimitAcctTypeEnum.TOTAL_CREDIT.getLimitAcctType().equals(txnLimitCfg.getLimitAcctType())) {
                        /*贷记卡限额信息赋值*/
                        if (MchntLimitEnum.MCHNT_REFUND.getLimitType().equals(limitType)) {
                            /*贷记账户单笔退款限额赋值*/
                            mchntLimitInfo.setOneCreditAmt(txnLimitCfg.getSingleRefundLimitAmt());
                            /*贷账户日累计退款限额赋值*/
                            mchntLimitInfo.setCreditDayTransAmt(txnLimitCfg.getDayRefundLimitAmt());
                        } else {
                            /*贷记账户单笔限额赋值*/
                            mchntLimitInfo.setOneCreditAmt(txnLimitCfg.getSingleLimitMaxAmt());
                            /*贷账户日累计限额赋值*/
                            mchntLimitInfo.setCreditDayTransAmt(txnLimitCfg.getDayLimitAmt());
                            /*贷记账户月累计限额赋值*/
                            mchntLimitInfo.setCreditMonthTransAmt(txnLimitCfg.getMonthLimitAmt());
                        }
                    } else if (LimitAcctTypeEnum.ALL.getLimitAcctType().equals(txnLimitCfg.getLimitAcctType())) {
                        /*不区分账户类型*/
                        if (MchntLimitEnum.MCHNT_REFUND.getLimitType().equals(limitType)) {
                            /*日累计退款限额*/
                            mchntLimitInfo.setDayTransAmt(txnLimitCfg.getDayRefundLimitAmt());
                        } else {
                            /*日累计限额*/
                            mchntLimitInfo.setDayTransAmt(txnLimitCfg.getDayLimitAmt());
                            /*月累计限额*/
                            mchntLimitInfo.setMonthTransAmt(txnLimitCfg.getMonthLimitAmt());
                        }
                    }
                }


                String statisDay = DateUtil.getCurrentDate();
                String statisMonth = DateUtil.getCurrentDateTime("yyyyMM");
                TxnLimitStatisMapper txnLimitStatisMapper = new TxnLimitStatisMapperImpl();
                if (!"03".equals(limitType)) {
                    limitInst = mchntNo;
                }
                /*查询日累计限额信息*/
                rglog.info("查询日累计已使用额度");
                List<TxnLimitStatis> txnLimitDayStatis = txnLimitStatisMapper.selectTxnLimitStatisByLimitInst(instId, statisDay, "D", limitInst);
                if (!CollectionUtils.isEmpty(txnLimitDayStatis)) {
                    if ("01".equals(limitType) || "11".equals(limitType)) {
                        txnLimitDayStatis = txnLimitDayStatis.stream().filter(item -> ("01".equals(item.getLimitType()) || "11".equals(item.getLimitType()))).collect(Collectors.toList());
                    } else {
                        txnLimitDayStatis = txnLimitDayStatis.stream().filter(item -> limitType.equals(item.getLimitType())).collect(Collectors.toList());
                    }
                }
                //借记退款日累计金额
                String dayDebitRefundTransAmt = "0";
                //贷记退款日累计金额
                String dayCreditRefundTransAmt = "0";
                //全类型退款日累计金额
                String dayAllRefundTransAmt = "0";
                //借记日累计金额
                String dayDebitTransAmt = "0";
                //贷记日累计金额
                String dayCreditTransAmt = "0";
                //全类型日累计金额
                String dayAllTransAmt = "0";

                if (!CollectionUtils.isEmpty(txnLimitDayStatis)) {
                    for (TxnLimitStatis txnLimitStatis : txnLimitDayStatis) {
                        if (LimitAcctTypeEnum.TOTAL_DEBIT.getLimitAcctType().equals(txnLimitStatis.getLimitAcctType())) {
                            if (MchntLimitEnum.MCHNT_REFUND.getLimitType().equals(limitType)) {
                                //借记日累计退款金额赋值
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getRefundTransAmt())) {
                                    dayDebitRefundTransAmt = AmountUtil.addition(dayDebitRefundTransAmt, txnLimitStatis.getRefundTransAmt());
                                }
                            } else {
                                //借记日累计金额赋值
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getDebitTransAmt())) {
                                    dayDebitTransAmt = AmountUtil.addition(dayDebitTransAmt, txnLimitStatis.getDebitTransAmt());
                                }
                            }
                        } else if (LimitAcctTypeEnum.TOTAL_CREDIT.getLimitAcctType().equals(txnLimitStatis.getLimitAcctType())) {
                            if (MchntLimitEnum.MCHNT_REFUND.getLimitType().equals(limitType)) {
                                //贷记日累计退款金额赋值
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getRefundTransAmt())) {
                                    dayCreditRefundTransAmt = AmountUtil.addition(dayCreditRefundTransAmt, txnLimitStatis.getRefundTransAmt());
                                }
                            } else {
                                //贷记日累计金额赋值
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getCreditTransAmt())) {
                                    dayCreditTransAmt = AmountUtil.addition(dayCreditTransAmt, txnLimitStatis.getCreditTransAmt());
                                }
                            }
                        } else if (LimitAcctTypeEnum.ALL.getLimitAcctType().equals(txnLimitStatis.getLimitAcctType())) {
                            if (MchntLimitEnum.MCHNT_REFUND.getLimitType().equals(limitType)) {
                                //全类型日累计退款金额
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getRefundTransAmt())) {
                                    dayAllRefundTransAmt = AmountUtil.addition(dayAllRefundTransAmt, txnLimitStatis.getRefundTransAmt());
                                }
                            } else {
                                //全类型日累计金额
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getTotalTransAmt())) {
                                    dayAllTransAmt = AmountUtil.addition(dayAllTransAmt, txnLimitStatis.getTotalTransAmt());
                                }
                            }
                        }
                    }
                }

                /*查询月累计限额信息*/
                rglog.info("查询月累计已使用额度");
                List<TxnLimitStatis> txnLimitMonthStatis = txnLimitStatisMapper.selectTxnLimitStatisByLimitInst(instId, statisMonth, "M", limitInst);
                if (!CollectionUtils.isEmpty(txnLimitMonthStatis)) {
                    if ("01".equals(limitType) || "11".equals(limitType)) {
                        txnLimitMonthStatis = txnLimitMonthStatis.stream().filter(item -> ("01".equals(item.getLimitType()) || "11".equals(item.getLimitType()))).collect(Collectors.toList());
                    } else {
                        txnLimitMonthStatis = txnLimitMonthStatis.stream().filter(item -> limitType.equals(item.getLimitType())).collect(Collectors.toList());
                    }
                }

                //借记退款月累计金额
                String monthDebitRefundTransAmt = "0";
                //贷记退款月累计金额
                String monthCreditRefundTransAmt = "0";
                //全类型退款月累计金额
                String monthAllRefundTransAmt = "0";
                //借记月累计金额
                String monthDebitTransAmt = "0";
                //贷记月累计金额
                String monthCreditTransAmt = "0";
                //全类型月累计金额
                String monthAllTransAmt = "0";

                if (!CollectionUtils.isEmpty(txnLimitMonthStatis)) {
                    for (TxnLimitStatis txnLimitStatis : txnLimitMonthStatis) {
                        if (LimitAcctTypeEnum.TOTAL_DEBIT.getLimitAcctType().equals(txnLimitStatis.getLimitAcctType())) {
                            if (MchntLimitEnum.MCHNT_REFUND.getLimitType().equals(limitType)) {
                                //借记退款月累计金额赋值
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getRefundTransAmt())) {
                                    monthDebitRefundTransAmt = AmountUtil.addition(monthDebitRefundTransAmt, txnLimitStatis.getRefundTransAmt());
                                }
                            } else {
                                //借记月累计金额赋值
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getTotalTransAmt())) {
                                    monthDebitTransAmt = AmountUtil.addition(monthDebitTransAmt, txnLimitStatis.getTotalTransAmt());
                                }
                            }
                        } else if (LimitAcctTypeEnum.TOTAL_CREDIT.getLimitAcctType().equals(txnLimitStatis.getLimitAcctType())) {
                            if (MchntLimitEnum.MCHNT_REFUND.getLimitType().equals(limitType)) {
                                //贷记退款月累计金额
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getRefundTransAmt())) {
                                    monthCreditRefundTransAmt = AmountUtil.addition(monthCreditRefundTransAmt, txnLimitStatis.getRefundTransAmt());
                                }
                            } else {
                                //贷记月累计金额
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getCreditTransAmt())) {
                                    monthCreditTransAmt = AmountUtil.addition(monthCreditTransAmt, txnLimitStatis.getCreditTransAmt());
                                }
                            }
                        } else if (LimitAcctTypeEnum.ALL.getLimitAcctType().equals(txnLimitStatis.getLimitAcctType())) {
                            if (MchntLimitEnum.MCHNT_REFUND.getLimitType().equals(limitType)) {
                                //全类型退款月累计金额
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getRefundTransAmt())) {
                                    monthAllRefundTransAmt = AmountUtil.addition(monthAllRefundTransAmt, txnLimitStatis.getRefundTransAmt());
                                }
                            } else {
                                //全类型月累计金额
                                if (!StringUtil.isEmptyOrNull(txnLimitStatis.getTotalTransAmt())) {
                                    monthAllTransAmt = AmountUtil.addition(monthAllTransAmt, txnLimitStatis.getTotalTransAmt());
                                }
                            }
                        }
                    }
                }

                if (MchntLimitEnum.MCHNT_REFUND.getLimitType().equals(limitType)) {
                    mchntLimitInfo.setUsedCreditDayTransAmt(dayCreditRefundTransAmt);
                    mchntLimitInfo.setUsedDebitDayTransAmt(dayDebitRefundTransAmt);
                    mchntLimitInfo.setUsedDayTransAmt(dayAllRefundTransAmt);
                    mchntLimitInfo.setUsedDebitMonthTransAmt(monthDebitRefundTransAmt);
                    mchntLimitInfo.setUsedCreditMonthTransAmt(monthCreditRefundTransAmt);
                    mchntLimitInfo.setUsedMonthTransAmt(monthAllRefundTransAmt);
                } else {
                    mchntLimitInfo.setUsedCreditDayTransAmt(dayCreditTransAmt);
                    mchntLimitInfo.setUsedDebitDayTransAmt(dayDebitTransAmt);
                    mchntLimitInfo.setUsedDayTransAmt(dayAllTransAmt);
                    mchntLimitInfo.setUsedDebitMonthTransAmt(monthDebitTransAmt);
                    mchntLimitInfo.setUsedCreditMonthTransAmt(monthCreditTransAmt);
                    mchntLimitInfo.setUsedMonthTransAmt(monthAllTransAmt);
                }
                mchntLimitInfoList.add(mchntLimitInfo);
            }
        } catch (Exception e) {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
            rglog.error("查询限额信息表异常:<{}>", byteArrayOutputStream.toString());
        }
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        MchntQuotaInfoQueryResponse mchntQuotaInfoQueryResponse = (MchntQuotaInfoQueryResponse) bizResponse.getResult();
        ConvertUtil.convertInput(mchntQuotaInfoQueryResponse);
    }
}
